package trocabi.view;

import trocabi.Renderer.DefaultCellRenderer;
import trocabi.Renderer.ColorCellRenderer;
import trocabi.Renderer.BoldCellRenderer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import trocabi.TROCABI;
import trocabi.Renderer.JButtonCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JOptionPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import trocabi.DAO.DAOArticle;
import trocabi.Socle.SwingTools;
import trocabi.Socle.TechnicalException;
import trocabi.model.Article;
import trocabi.service.ArticleServices;

public class GuiVente extends JFrame implements TableModelListener, ListSelectionListener {
    private static final Logger      logger = Logger.getLogger("trocabi.view.GuiVente");
    private DAOArticle               daoArticle = DAOArticle.getInstance();
    private ArticleServices          articleServices=new ArticleServices();
    private JButton                  btAnnuler;
    private JButton                  btValider;   // TODO: faire disparaitre ce bouton
    private JButton                  btBraderie;
    private JButton                  btValiderVente;
    private JTableModelVenteArticles articlesModele;
    private JTable                   jTableArticles;
    private JPanel pContentPanel;
    private JLabel lTitre;
    private JPanel pCenter;
    private JPanel pSpeciaux;
    private JScrollPane spListe;
  
   
    private JPanel pBoutons;
    private JTextField tfCodeBarre;
    private JTextField tfPrix;
   
    private JLabel lTotal;

    public GuiVente() {
        initComponents();
    }

    private void initComponents() {
        this.setTitle("Vente");
        this.setSize(500, 500);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

        // Content panel de type BorderPanel --> nord = titre / centre = contenu / sud = licence, droits, auteurs ...
        pContentPanel = new JPanel(new BorderLayout());
        pContentPanel.setBackground(Color.white);
        this.setContentPane(pContentPanel);

        // Titre
        lTitre = new JLabel("<html><body><br />Vente :<br /><br /></body></html>");
        lTitre.setHorizontalAlignment(SwingConstants.CENTER);
        pContentPanel.add(lTitre, BorderLayout.NORTH);

        /*
         * Que du gridBagLayout
         * Panel de 4 lignes --> lignes 1,2 et 4 contiennent des panels (ligne 2 = scrollpanel / les autres = GridBagLayout)
         */
        pCenter = new JPanel(new GridBagLayout());
        GridBagConstraints tmp = new GridBagConstraints();
        // Sous-panel "Cas spéciaux"
        pSpeciaux = new JPanel(new GridBagLayout());
        tmp.gridx = 0;
        tmp.gridy = 0;
        tmp.insets = new Insets(10, 10, 0, 10);
        tmp.anchor = GridBagConstraints.LINE_START;
        pSpeciaux.add(new JLabel("Saisie du code barre :"), tmp);
        tmp.gridy = 1;
        pSpeciaux.add(new JLabel("Prix :"), tmp);
        tfPrix = new JTextField();
        tfPrix.setPreferredSize(new Dimension(150, 20));
        tfPrix.setMinimumSize(new Dimension(150, 20));
        tmp.gridx = 1;
        pSpeciaux.add(tfPrix, tmp);
        tfCodeBarre = new JTextField();
        tfCodeBarre.setPreferredSize(new Dimension(150, 20));
        tfCodeBarre.setMinimumSize(new Dimension(150, 20));
        tmp.gridy = 0;
        pSpeciaux.add(tfCodeBarre, tmp);
        btValider = new JButton("Valider");
        btValider.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                validerCodeBarre(tfCodeBarre.getText());
            }
        });
        tmp.gridx = 2;
        pSpeciaux.add(btValider, tmp);
        btBraderie = new JButton("Braderie");
        btBraderie.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                validerCodeBarre(tfCodeBarre.getText());
            }
        });
        tmp.gridy = 1;
        pSpeciaux.add(btBraderie, tmp);
        tmp.gridx = 0;
        tmp.gridy = 0;
        tmp.insets = new Insets(0, 10, 0, 10);
        pCenter.add(pSpeciaux, tmp);
        // Sous-panel "Afficher Résultats Recherche"
        articlesModele = new JTableModelVenteArticles();
        jTableArticles = new JTable(articlesModele);
        jTableArticles.getModel().addTableModelListener(this);
        jTableArticles.setRowHeight(30);
        int[] colSize = { 120, 85, 110, 70, 80, 80, 80, 70, 70, 170 };
        SwingTools.setJTableSize(jTableArticles, colSize);
        jTableArticles.setDefaultRenderer(Object.class, new DefaultCellRenderer());
        jTableArticles.getColumnModel().getColumn(0).setCellRenderer(new JButtonCellRenderer());
        jTableArticles.getColumnModel().getColumn(0).setCellEditor(new JButtonCellEditor(new JCheckBox(),articlesModele));
        jTableArticles.getColumnModel().getColumn(1).setCellRenderer(new BoldCellRenderer());
        jTableArticles.getColumnModel().getColumn(8).setCellRenderer(new ColorCellRenderer());
        jTableArticles.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        jTableArticles.getSelectionModel().addListSelectionListener(this);
        TableRowSorter<TableModel> rsSorter = new <TableModel>TableRowSorter(jTableArticles.getModel());
        jTableArticles.setRowSorter(rsSorter);
        rsSorter.setSortsOnUpdates(true);
        spListe = new JScrollPane(jTableArticles);
        tmp.gridx = 0;
        tmp.gridy = 1;
        tmp.weighty = 1;
        tmp.insets = new Insets(10, 10, 0, 10);
        tmp.fill = GridBagConstraints.BOTH;
        pCenter.add(spListe, tmp);
        // Label "Total"
        tmp.gridy = 2;
        tmp.weighty = 0;
        lTotal = new JLabel("Total :       €");
        pCenter.add(lTotal, tmp);
        // Sous-panel "Boutons"
        pBoutons = new JPanel(new GridBagLayout());
        btAnnuler = new JButton("Tout annuler");
        btAnnuler.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                setDefault();
            }
        });
        tmp.gridy = 0;
        tmp.fill = GridBagConstraints.NONE;
        tmp.anchor = GridBagConstraints.LINE_START;
        pBoutons.add(btAnnuler, tmp);
        btValiderVente = new JButton("Valider la vente");
        btValiderVente.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                validerVente();
            }
        });
        tmp.gridx = 1;
        tmp.weightx = 1;
        tmp.anchor = GridBagConstraints.LINE_END;
        pBoutons.add(btValiderVente, tmp);
        tmp.gridx = 0;
        tmp.gridy = 3;
        tmp.insets = new Insets(10, 10, 10, 10);
        tmp.fill = GridBagConstraints.HORIZONTAL;
        pCenter.add(pBoutons, tmp);
        pContentPanel.add(pCenter, BorderLayout.CENTER);
    }

    public void setDefault() {
        this.setLocationRelativeTo(null);
        lTotal.setText("Total :       €");
        tfCodeBarre.setText("");
        tfPrix.setText("");
        btAnnuler.setEnabled(false);
        btValiderVente.setEnabled(false);
        btBraderie.setEnabled(false);
        int i, j = articlesModele.getRowCount();
        articlesModele.removeAll();
    }

    public JTable getJTable() {
        return jTableArticles;
    }

    public void calculPrixTotal() {
        int i;
        double prixTotal = 0;
        for (i = 0; i < articlesModele.getRowCount(); i++) {
            prixTotal += articlesModele.getRow(i, jTableArticles).getPrixAchat() * (1 + articlesModele.getRow(i, jTableArticles).getTxMarge());
        }
        lTotal.setText("Total :       " + TROCABI.dfFormat_Prix.format(prixTotal) + "€");
    }

    @Override
    public void tableChanged(TableModelEvent tme) {
        if (tme.getSource() == jTableArticles.getModel()) {
            if (articlesModele.getRowCount() > 0) {
                btAnnuler.setEnabled(true);
                btValiderVente.setEnabled(true);
                calculPrixTotal();
            } else {
                btAnnuler.setEnabled(false);
                btValiderVente.setEnabled(false);
                lTotal.setText("Total :       €");
            }
        } else {
            TROCABI.fenetreExterne(TROCABI.ERREUR, "Erreur inattendue : source de l'évènement inconnue");
        }
    }

    @Override
    public void valueChanged(ListSelectionEvent lse) {
        if (lse.getSource() == jTableArticles.getSelectionModel()) {
            if (jTableArticles.getSelectedRowCount() > 0) {
                btBraderie.setEnabled(true);
            } else {
                btBraderie.setEnabled(false);
            }
        } else {
            TROCABI.fenetreExterne(TROCABI.ERREUR, "Erreur inattendue : source de l'évènement inconnue");
        }
    }
    
    void validerCodeBarre(String codeBarre) { // TODO: validation automatique du code barre
        /*
         if (formatageIntPositif(CODE_BARRE, sDonnee) == -1) {
         fenetreExterne(ERREUR, "Le champ \"Code barre\" ne respecte pas le format de donnée attendu.\nCi-dessous le format attendu :\n     - Code Barre : ##########\n\nLes '#' correspondent à un chiffre (0 à 9)");
         return;
         }
         * */

        // Sélection en BDD par code barre
        ArrayList<Article> listArticles;
        ArrayList<String[]> listConditions_Article = new <String[]> ArrayList();
        String[] stabConditions_Articles;
        // Condition sur le numéro d'article
        stabConditions_Articles = new String[4];
        stabConditions_Articles[DAOArticle.iID_DB] = DAOArticle.FD_ID;
        stabConditions_Articles[DAOArticle.iVALEUR] = codeBarre;
        stabConditions_Articles[DAOArticle.iMODE_COMPARAISON] = DAOArticle.sEGAL_STRICT;
        stabConditions_Articles[DAOArticle.iMODE_TRIE] = null;
        listConditions_Article.add(stabConditions_Articles);
        try {
            // Recherche dans la BDD
            listArticles = daoArticle.listSelect(listConditions_Article, null, DAOArticle.iNO_LIMIT);
            if (listArticles == null) {
                logger.info(String.format("Vente: article '%s' non trouvé", codeBarre));
                TROCABI.fenetreExterne(TROCABI.ERREUR, "Aucun élément trouvé. Vérifiez votre code barre.");
                return;
            }
            if (listArticles.size() != 1) {
                logger.severe(String.format("Vente: plusieurs articles trouves pour l'id '%s'", codeBarre));
                TROCABI.fenetreExterne(TROCABI.ERREUR, "Erreur inattendue lors de la sélection de l'article.");
                return;
            }
            if (listArticles.get(0).getSituation().equals("VENDU")) {
                logger.info(String.format("Vente: article '%s' non trouvé", codeBarre));
                TROCABI.fenetreExterne(TROCABI.ERREUR, "L'article sélectionné est vendu. Corrigez la situation de l'article si ce n'est pas le cas.");
                return;
            }
            articlesModele.add(listArticles.get(0));
        } catch (TechnicalException e) {
            TROCABI.fenetreExterne(TROCABI.ERREUR, e.getMessage());
        }
    }
    
    void venteBraderie() { // TODO: check cas braderie
          TROCABI.fenetreExterne(TROCABI.ERREUR, "Not Yet Implemented");
          
        /*
        // vérification champ "Prix"
        double dPrix = formatageDoublePositif(tfPrix.getText()), 2);
        if (dPrix == -1) {
            fenetreExterne(ERREUR, "Le champ \"Prix\" ne respecte pas le format de donnée attendu.\nCi-dessous le format attendu :\n     - Prix : un nombre décimal strictement positif (la séparation de la partie entière et de la partie décimale est faites par un '.')");
            return;
        }
        // vérification SITUATION des articles sélectionnés = DONNÉ
        
        int[] iSelectedRows = fVente.getJTable().getSelectedRows();
        for (i = 0; i < fVente.getJTable().getSelectedRowCount(); i++) {
            if (!fVente.getJTableModele().getRow(iSelectedRows[i], fVente.getJTable()).getSituation().equals("DONNÉ")) {
                fenetreExterne(ERREUR, (fVente.getJTable().getSelectedRowCount() != 1) ? "Les articles sélectionnés n'ont pas été donnés par leur dépositaire, ils ne peuvent donc pas être bradés." : "L'article sélectionné n'a pas été donné par son dépositaire, il ne peut donc pas être bradé.");
                return;
            }
        }
        
        
        // Mise à jour du prix
        while (fVente.getJTable().getSelectedRowCount() != 0) {
            // Liste des champs à modifier
            ArrayList<String[]> listMAJInfos_Article = new <String[]> ArrayList();
            String[] stabMAJ_Articles;
            // MAJ Date de changement d'état
            stabMAJ_Articles = new String[2];
            stabMAJ_Articles[DAOArticle.iID_DB] = DAOArticle.sID_DB_DATE_CHANGEMENT_ETAT;
            stabMAJ_Articles[DAOArticle.iVALEUR] = (new java.sql.Date((new Date()).getTime())).toString();
            listMAJInfos_Article.add(stabMAJ_Articles);
            // MAJ Prix
            stabMAJ_Articles = new String[2];
            stabMAJ_Articles[DAOArticle.iID_DB] = DAOArticle.sID_DB_PRIX_ACHAT;
            stabMAJ_Articles[DAOArticle.iVALEUR] = Double.toString(dPrix * (1 / (1 + fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getMarge())));
            listMAJInfos_Article.add(stabMAJ_Articles);
            // Liste des conditions de modification
            ArrayList<String[]> listMAJConditions_Articles = new <String[]> ArrayList();
            String[] stabMAJ_Conditions_Articles;
            // Condition sur le numéro d'article
            stabMAJ_Conditions_Articles = new String[3];
            stabMAJ_Conditions_Articles[DAOArticle.iID_DB] = DAOArticle.sID_DB_CODE_ARTICLE;
            stabMAJ_Conditions_Articles[DAOArticle.iVALEUR] = Long.toString(fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getId());
            stabMAJ_Conditions_Articles[DAOArticle.iMODE_COMPARAISON] = DAOArticle.sEGAL_STRICT;
            listMAJConditions_Articles.add(stabMAJ_Conditions_Articles);

            if (!daoArticle.bUpdate(listMAJInfos_Article, listMAJConditions_Articles)) {
                fenetreExterne(ERREUR, "Erreur inattendue lors de la mise à jour de l'article.");
                return;
            }
            fVente.getJTableModele().Add(new Article(
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getId(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getIdDepositaire(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getDescription(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getCodeAspect(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getCodeType(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getCodeGenre(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getCouleur(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getSituation(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getDateChangementEtat(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getCommentaire(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getIdCaisse(),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getDateDepot(),
                    dPrix * (1 / (1 + fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getMarge())),
                    fVente.getJTableModele().getRow(iSelectedRows[0], fVente.getJTable()).getMarge()));
            fVente.getJTableModele().Remove(iSelectedRows[0], fVente.getJTable());
            iSelectedRows = fVente.getJTable().getSelectedRows();
        }
        */
    }
    
    void validerVente() {
        ArrayList<Article> articlesVendus;
        int retour = JOptionPane.showOptionDialog(null,
                "Le paiement a-t-il été effectué ?", "Valider la vente",
                JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE,
                new ImageIcon(".\\Ressources\\Check.png"), null, null);
        if (retour != JOptionPane.YES_OPTION) {
            return;
        }
        articlesVendus = articlesModele.getArticles();
        int i = 0;
        try {
            for (Article article : articlesVendus) {
                article.setDateChangementEtat(new Date());
                article.setSituation(Article.Etat.VENDU);
                articleServices.update(article);
            }
        } catch (TechnicalException ex) {
            Logger.getLogger(GuiVente.class.getName()).log(Level.SEVERE, null, ex);
            TROCABI.fenetreExterne(TROCABI.ERREUR, "Erreur inattendue lors de la mise à jour de l'article.");
        }
    }
}
